package com.ruoyi.system.common;

import com.google.gson.Gson;
import com.ruoyi.system.service.ISqlService;
import lombok.Data;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class PluginJarTools {
//
//    private static HashMap<String,String> clazzType = new HashMap<>();
//    static {
//        //基本类型
//        clazzType.put("byte","java.lang.Byte");
//        clazzType.put("short","java.lang.Short");
//        clazzType.put("int","java.lang.Integer");
//        clazzType.put("long","java.lang.Long");
//        clazzType.put("double","java.lang.Double");
//        clazzType.put("float","java.lang.Float");
//        clazzType.put("boolean","java.lang.Boolean");
//        //包装类型
//        clazzType.put("java.lang.Byte","java.lang.Byte");
//        clazzType.put("java.lang.Short","java.lang.Short");
//        clazzType.put("java.lang.Integer","java.lang.Integer");
//        clazzType.put("java.lang.Long","java.lang.Long");
//        clazzType.put("java.lang.Double","java.lang.Double");
//        clazzType.put("java.lang.Float","java.lang.Float");
//        clazzType.put("java.lang.Boolean","java.lang.Boolean");
//        //对象类型
//        clazzType.put("java.sql.Date","java.lang.String");
//        clazzType.put("java.util.Date","java.lang.String");
//        clazzType.put("java.sql.Time","java.lang.String");
//        clazzType.put("java.lang.String","java.lang.String");
//    }
//
//    private static HashMap<String, Class> classHashMap = new HashMap<>();
//    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(2, 4,
//            200, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
//
//    public static PluginInfo getInfoForFile(String path) {
//
//        URL[] urls;
//        try {
//            urls = new URL[]{new URL("http://127.0.0.1" + path)};
//        } catch (MalformedURLException e) {
//            throw new RuntimeException("插件路径错误", e);
//        }
//
//        // 创建URLClassLoader实例
//        URLClassLoader classLoader = new URLClassLoader(urls);
//        return getInfoForClassLoader(classLoader,path);
//    }
//    public static PluginInfo getInfoForObject(Object o) {
//        ClassLoader classLoader = o.getClass().getClassLoader();
//        return getInfoForClassLoader(classLoader,classLoader.getResource("").toString());
//    }
//    private static PluginInfo getInfoForClassLoader(ClassLoader classLoader,String path) {
//        IndsvrPlugin plugin = new IndsvrPlugin();
//        List<IndsvrPluginParameter> inData;
//        List<IndsvrPluginParameter> outData;
//        // 加载类
//        Class<?> metaInfo;
//        try {
//            metaInfo = Class.forName("com.indsvr.META_INFO", true, classLoader);
//        } catch (ClassNotFoundException e) {
//            throw new RuntimeException("未发现元信息文件", e);
//        }
//
//        try {
//            Class<?> mainClass1 = (Class<?>) metaInfo.getField("MAIN_CLASS").get(null);
//            String mainClass = mainClass1.getCanonicalName();
//            plugin.setPluginMainclass(mainClass);
//            mainClass1.getMethod("run", String.class,Object.class);
//        } catch (IllegalAccessException e) {
//            throw new RuntimeException("MAIN_CLASS可见性设置错误，应为public", e);
//        } catch (NoSuchFieldException e) {
//            throw new RuntimeException("元信息文件中，MAIN_CLASS未配置", e);
//        } catch (NoSuchMethodException e) {
//            throw new RuntimeException("run(String data)方法不存在", e);
//        }
//
//        try {
//            int version = (int) metaInfo.getField("VERSION").get(null);
//            plugin.setPluginVersion((long) version);
//        } catch (IllegalAccessException e) {
//            throw new RuntimeException("VERSION可见性设置错误，应为public", e);
//        } catch (NoSuchFieldException e) {
//            throw new RuntimeException("元信息文件中，VERSION未配置", e);
//        }
//
//        try {
//            String name = (String) metaInfo.getField("NAME").get(null);
//            plugin.setPluginName(name);
//        } catch (IllegalAccessException e) {
//            throw new RuntimeException("NAME可见性设置错误，应为public", e);
//        } catch (NoSuchFieldException e) {
//            throw new RuntimeException("元信息文件中，NAME未配置", e);
//        }
//
//        try {
//            String description = (String) metaInfo.getField("DESCRIPTION").get(null);
//            plugin.setRemark(description);
//        } catch (IllegalAccessException e) {
//            throw new RuntimeException("DESCRIPTION可见性设置错误，应为public", e);
//        } catch (NoSuchFieldException e) {
//            throw new RuntimeException("元信息文件中，DESCRIPTION未配置", e);
//        }
//
//        plugin.setPluginStatus(2);
//        plugin.setPluginCode(Md5Utils.hash(plugin.getPluginName()));
//        plugin.setPluginPath(path);
//
//
//        //io的描述
//        Class<? extends Annotation> parameterClazz = null;
//        try {
//            parameterClazz = (Class<? extends Annotation>) Class.forName("com.indsvr.common.Parameter", true, classLoader);
//        } catch (ClassNotFoundException e) {
//            throw new RuntimeException("com.indsvr.common.Parameter不存在", e);
//        }
//        //io
//        Class<?> inDataClazz = null;
//        try {
//            inDataClazz = Class.forName("com.indsvr.io.InData", true, classLoader);
//        } catch (ClassNotFoundException e) {
//            throw new RuntimeException("com.indsvr.io.InData不存在", e);
//        }
//
//        //out
//        Class<?> outDataClazz = null;
//        try {
//            outDataClazz = Class.forName("com.indsvr.io.OutData", true, classLoader);
//        } catch (ClassNotFoundException e) {
//            throw new RuntimeException("com.indsvr.io.OutData不存在", e);
//        }
//
//
//        try {
//            inData = getParameter(inDataClazz, parameterClazz);
//        } catch (Exception e) {
//            throw new RuntimeException("输入参数获取失败", e);
//        }
//        try {
//            outData = getParameter(outDataClazz, parameterClazz);
//        } catch (Exception e) {
//            throw new RuntimeException("输出参数获取失败", e);
//        }
//
//
//        // 关闭ClassLoader，释放资源
//        try {
//            if (classLoader instanceof URLClassLoader) {
//                URLClassLoader u = (URLClassLoader) classLoader;
//                u.close();
//            }
//        } catch (IOException e) {
//            throw new RuntimeException("jar包释放失败", e);
//        }
//
//
//        PluginInfo pluginInfo = new PluginInfo();
//        pluginInfo.setPlugin(plugin);
//        pluginInfo.setInData(inData);
//        pluginInfo.setOutData(outData);
//        return pluginInfo;
//    }
//
//
//    private static String gClassloader(PluginInfo pluginInfo) {
//        URL[] urls = new URL[0];
//        try {
//            urls = new URL[]{new URL("http://127.0.0.1" + pluginInfo.plugin.getPluginPath())};
//        } catch (MalformedURLException e) {
//            throw new RuntimeException("URL解析失败",e);
//        }
//        // 创建URLClassLoader实例
//        URLClassLoader classLoader  = new URLClassLoader(urls);
//        // 加载类
//        Class<?> mainClazz = null;
//        try {
//            mainClazz = Class.forName(pluginInfo.plugin.getPluginMainclass(), true, classLoader);
//        } catch (ClassNotFoundException e) {
//            throw new RuntimeException("mainclass加载失败",e);
//        }
//        String s = gKey(pluginInfo);
//        classHashMap.put(s, mainClazz);
//        return s;
//    }
//
//    public static String execute(PluginInfo pluginInfo, String in, ISqlService sqlMapper, ExecuteCallBack callBack){
//        String key = gClassloader(pluginInfo);
//        sqlMapper.setInfo(pluginInfo);
//        sqlMapper.setSessionKey(key);
//
//        EXECUTOR.execute(() -> {
//
//            Class<?> aClass = classHashMap.get(key);
//            if (aClass==null) {
//                throw new RuntimeException("key不存在，请检查");
//            }
//
//            HashMap<String, Object> hashMap = new Gson().fromJson(in, HashMap.class);
//            for (IndsvrPluginParameter inDatum : pluginInfo.inData) {
//                Object o = hashMap.get(inDatum.getParameterCode());
//                if (inDatum.getParameterNullable()==0 && o ==null) {
//                    throw new RuntimeException("不可为空参数："+inDatum.getParameterName()+"("+inDatum.getParameterCode()+")");
//                }
//            }
//
//            String out = null;
//            try {
//                Method run = aClass.getMethod("run", String.class,Object.class);
//                out = (String) run.invoke(aClass.getDeclaredConstructor().newInstance(), in,sqlMapper);
//            } catch (InvocationTargetException e) {
//                out=e.getTargetException().getMessage();
//            } catch (NoSuchMethodException e) {
//                out="未找到run(String inData)方法";
//            } catch (IllegalAccessException e) {
//                out="非法访问异常";
//            } catch (InstantiationException e) {
//                out="实例化异常";
//            } finally {
//                try {
//                    String log = (String) aClass.getMethod("log").invoke(null);
//                    callBack.callback(in,out,log,key);
//                    URLClassLoader classLoader = (URLClassLoader) aClass.getClassLoader();
//                    classLoader.close();
//                    classHashMap.remove(key);
//                }catch (Exception e){
//                    System.out.println("写入执行日志失败："+e.getMessage());
//                }
//            }
//
//        });
//        return key;
//    }
//
//    public static String logs(String key) throws Exception{
//        Class<?> aClass = classHashMap.get(key);
//        return (String) aClass.getMethod("log").invoke(null);
//    }
//
//
//    @Data
//    public static class PluginInfo {
//
//        private IndsvrPlugin plugin;
//        private List<IndsvrPluginParameter> inData;
//        private List<IndsvrPluginParameter> outData;
//
//
//        public PluginInfo build() {
//            for (IndsvrPluginParameter inDatum : inData) {
//                inDatum.setPluginId(this.plugin.getId());
//                inDatum.setPluginVersion(this.plugin.getPluginVersion());
//                inDatum.setParameterIo(1);
//            }
//            for (IndsvrPluginParameter outDatum : outData) {
//                outDatum.setPluginId(this.plugin.getId());
//                outDatum.setPluginVersion(this.plugin.getPluginVersion());
//                outDatum.setParameterIo(0);
//            }
//            return this;
//        }
//    }
//
//    public interface ExecuteCallBack{
//        void callback(String in, String out, String log, String key);
//    }
//
//
//    private static List<IndsvrPluginParameter> getParameter(Class<?> clazz, Class<? extends Annotation> annotationClazz) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//        ArrayList<IndsvrPluginParameter> indsvrPluginParameters = new ArrayList<>();
//        Field[] fields = clazz.getDeclaredFields();
//        for (Field field : fields) {
//            if (field.isAnnotationPresent(annotationClazz)) {
//                Annotation annotation = field.getAnnotation(annotationClazz);
//                //字段名
//                String name = (String) annotationClazz.getMethod("name").invoke(annotation);
//                //是否为空
//                boolean nullable = (boolean) annotationClazz.getMethod("nullable").invoke(annotation);
//                IndsvrPluginParameter e = new IndsvrPluginParameter();
//
//                e.setParameterCode(field.getName());
//                e.setParameterName(name);
//                e.setParameterNullable(nullable ? 1 : 0);
//
//                String name1 = field.getType().getName();
//                String parameterClassType = clazzType.get(name1);
//                e.setParameterClassType(parameterClassType);
//
//                indsvrPluginParameters.add(e);
//            }
//        }
//        return indsvrPluginParameters;
//    }
//
//    private static String gKey(PluginInfo pluginInfo) {
//        IndsvrPlugin plugin = pluginInfo.getPlugin();
//        return plugin.getPluginCode() + "." + plugin.getPluginVersion() + "." +  UUID.randomUUID();
//    }
}
